﻿using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;

namespace nhCore
{
    /// <summary>
    /// 云平台直连没完成，有客户需求时再做2022-12-30
    /// </summary>
    public class TcpClientIO : IO
    {
        private TcpClient client;

        /// <summary>
        /// IP地址
        /// </summary>
        public string HostName { get; set; }

        /// <summary>
        /// 端口
        /// </summary>
        public int RemotePort { get; set; }

        /// <summary>
        /// 本地终结点
        /// </summary>
        //IPEndPoint LocalEndPoint { get; set; }

        /// <summary>
        /// 服务器终结点
        /// </summary>
        //IPEndPoint RemoteIPEndPoint { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public ulong Interval { get; set; }

        /// <summary>
        /// 构造函数，TCP客户端
        /// </summary>
        /// <param name="aHostName"></param>
        /// <param name="aPort"></param>
        public TcpClientIO(string aHostName, int aPort)
        {
            this.HostName = aHostName;
            this.RemotePort = aPort;
            this.Name = "TCP客户端";
            this.Interval = 310;
        }


        /// <summary>
        /// 关闭IO
        /// </summary>
        /// <returns></returns>
        public override bool Close()
        {
            if (this.IsOpened)
            {
                IsOpened = false;
                client.Close();
            }
            return true;
        }

        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <returns></returns>
        public override bool Open(bool asyncComm = false)
        {
            this.client = new TcpClient();
            bool result = false;
            lock (this)
            {
                if (this.IsOpened)
                {
                    Debug.WriteLine($"已经连接到服务器，服务器地址：{HostName}:{RemotePort}");
                }
                else
                {
                    try
                    {
                        client.Connect(HostName, RemotePort);
                    }
                    catch (Exception ex)
                    {
                        IOListener.Error(ex.Message);
                    }
                    IsOpened = client.Connected;
                    if (IsOpened)
                    {
                        //LocalEndPoint = (IPEndPoint)_Client.Client.LocalEndPoint;
                        //RemoteIPEndPoint = (IPEndPoint)_Client.Client.RemoteEndPoint;
                        IOListener.Connected(this, client);
                        NetworkStream nStream = client.GetStream();
                        // byte[] buffer = new byte[2048];
                        ReadAsyncResult rResult = new ReadAsyncResult(1024, client);
                        nStream.BeginRead(rResult.Buffer, 0, rResult.Buffer.Length, new AsyncCallback(ReadComplete), rResult);
                        result = true;
                    }
                    result = IsOpened;
                }
            }
            return result;
        }

        /// <summary>
        /// 读取数据完成
        /// </summary>
        /// <param name="iar"></param>

        private void ReadComplete(IAsyncResult iar)
        {
            if (IsOpened)
            {
                ReadAsyncResult rResult = (ReadAsyncResult)iar.AsyncState;
                NetworkStream nStream = null;

                byte[] byt = rResult.Buffer;
                int len = 0;
                try
                {
                    nStream = rResult.Client.GetStream();//关软件时跳异常client可能已关闭
                    len = nStream.EndRead(iar);
                }
                catch (Exception)
                {
                    len = 0;
                }
                if (len <= 0)
                {
                    IsOpened = false;
                    IOListener.DisConnected(this, rResult.Client);
                }
                else
                {
                    byte[] buffer = new byte[len];
                    Array.Copy(byt, buffer, len);//返回数据复制到与返回长度一致的数组
                    // ReDim Preserve byt(len - 1)
                    IOListener.Received(this, rResult.Client, buffer);
                    nStream.BeginRead(rResult.Buffer, 0, rResult.Buffer.Length, new AsyncCallback(ReadComplete), rResult);
                }
            }
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="client"></param>
        /// <param name="byt"></param>
        /// <returns></returns>
        public override bool Send(object client, in object writeData)
        {
            byte[] byt = (byte[])writeData;
            TcpClient tcpClient = (TcpClient)client;
            bool result;
            try
            {
                NetworkStream nStream = tcpClient.GetStream();
                nStream.Write(byt, 0, byt.Length);
                result = true;
            }
            catch (Exception ex)
            {
                result = false;
                Debug.WriteLine(ex.ToString());
            }
            return result;
        }

        public override object SendAccept(object client, object writeData)
        {
            throw new NotImplementedException();
        }
    }
}
